/*
 * Copyright 2012 software2012team23
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// lib/handlebars/base.js
var Handlebars = {};

Handlebars.VERSION = "1.0.beta.6";

Handlebars.helpers = {};
Handlebars.partials = {};

Handlebars.registerHelper = function(name, fn, inverse) {
	if (inverse) {
		fn.not = inverse;
	}
	this.helpers[name] = fn;
};

Handlebars.registerPartial = function(name, str) {
	this.partials[name] = str;
};

Handlebars.registerHelper('helperMissing', function(arg) {
	if (arguments.length === 2) {
		return undefined;
	} else {
		throw new Error("Could not find property '" + arg + "'");
	}
});

var toString = Object.prototype.toString, functionType = "[object Function]";

Handlebars.registerHelper('blockHelperMissing', function(context, options) {
	var inverse = options.inverse || function() {
	}, fn = options.fn;

	var ret = "";
	var type = toString.call(context);

	if (type === functionType) {
		context = context.call(this);
	}

	if (context === true) {
		return fn(this);
	} else if (context === false || context == null) {
		return inverse(this);
	} else if (type === "[object Array]") {
		if (context.length > 0) {
			for (var i = 0, j = context.length; i < j; i++) {
				ret = ret + fn(context[i]);
			}
		} else {
			ret = inverse(this);
		}
		return ret;
	} else {
		return fn(context);
	}
});

Handlebars.registerHelper('each', function(context, options) {
	var fn = options.fn, inverse = options.inverse;
	var ret = "";

	if (context && context.length > 0) {
		for (var i = 0, j = context.length; i < j; i++) {
			ret = ret + fn(context[i]);
		}
	} else {
		ret = inverse(this);
	}
	return ret;
});

Handlebars.registerHelper('if', function(context, options) {
	var type = toString.call(context);
	if (type === functionType) {
		context = context.call(this);
	}

	if (!context || Handlebars.Utils.isEmpty(context)) {
		return options.inverse(this);
	} else {
		return options.fn(this);
	}
});

Handlebars.registerHelper('unless', function(context, options) {
	var fn = options.fn, inverse = options.inverse;
	options.fn = inverse;
	options.inverse = fn;

	return Handlebars.helpers['if'].call(this, context, options);
});

Handlebars.registerHelper('with', function(context, options) {
	return options.fn(context);
});

Handlebars.registerHelper('log', function(context) {
	Handlebars.log(context);
});
;
// lib/handlebars/compiler/parser.js
/* Jison generated parser */
var handlebars = (function() {

	var parser = {
		trace : function trace() {
		},
		yy : {},
		symbols_ : {
			"error" : 2,
			"root" : 3,
			"program" : 4,
			"EOF" : 5,
			"statements" : 6,
			"simpleInverse" : 7,
			"statement" : 8,
			"openInverse" : 9,
			"closeBlock" : 10,
			"openBlock" : 11,
			"mustache" : 12,
			"partial" : 13,
			"CONTENT" : 14,
			"COMMENT" : 15,
			"OPEN_BLOCK" : 16,
			"inMustache" : 17,
			"CLOSE" : 18,
			"OPEN_INVERSE" : 19,
			"OPEN_ENDBLOCK" : 20,
			"path" : 21,
			"OPEN" : 22,
			"OPEN_UNESCAPED" : 23,
			"OPEN_PARTIAL" : 24,
			"params" : 25,
			"hash" : 26,
			"param" : 27,
			"STRING" : 28,
			"INTEGER" : 29,
			"BOOLEAN" : 30,
			"hashSegments" : 31,
			"hashSegment" : 32,
			"ID" : 33,
			"EQUALS" : 34,
			"pathSegments" : 35,
			"SEP" : 36,
			"$accept" : 0,
			"$end" : 1
		},
		terminals_ : {
			2 : "error",
			5 : "EOF",
			14 : "CONTENT",
			15 : "COMMENT",
			16 : "OPEN_BLOCK",
			18 : "CLOSE",
			19 : "OPEN_INVERSE",
			20 : "OPEN_ENDBLOCK",
			22 : "OPEN",
			23 : "OPEN_UNESCAPED",
			24 : "OPEN_PARTIAL",
			28 : "STRING",
			29 : "INTEGER",
			30 : "BOOLEAN",
			33 : "ID",
			34 : "EQUALS",
			36 : "SEP"
		},
		productions_ : [ 0, [ 3, 2 ], [ 4, 3 ], [ 4, 1 ], [ 4, 0 ], [ 6, 1 ],
				[ 6, 2 ], [ 8, 3 ], [ 8, 3 ], [ 8, 1 ], [ 8, 1 ], [ 8, 1 ],
				[ 8, 1 ], [ 11, 3 ], [ 9, 3 ], [ 10, 3 ], [ 12, 3 ], [ 12, 3 ],
				[ 13, 3 ], [ 13, 4 ], [ 7, 2 ], [ 17, 3 ], [ 17, 2 ],
				[ 17, 2 ], [ 17, 1 ], [ 25, 2 ], [ 25, 1 ], [ 27, 1 ],
				[ 27, 1 ], [ 27, 1 ], [ 27, 1 ], [ 26, 1 ], [ 31, 2 ],
				[ 31, 1 ], [ 32, 3 ], [ 32, 3 ], [ 32, 3 ], [ 32, 3 ],
				[ 21, 1 ], [ 35, 3 ], [ 35, 1 ] ],
		performAction : function anonymous(yytext, yyleng, yylineno, yy,
				yystate, $$, _$) {

			var $0 = $$.length - 1;
			switch (yystate) {
			case 1:
				return $$[$0 - 1]
				break;
			case 2:
				this.$ = new yy.ProgramNode($$[$0 - 2], $$[$0])
				break;
			case 3:
				this.$ = new yy.ProgramNode($$[$0])
				break;
			case 4:
				this.$ = new yy.ProgramNode([])
				break;
			case 5:
				this.$ = [ $$[$0] ]
				break;
			case 6:
				$$[$0 - 1].push($$[$0]);
				this.$ = $$[$0 - 1]
				break;
			case 7:
				this.$ = new yy.InverseNode($$[$0 - 2], $$[$0 - 1], $$[$0])
				break;
			case 8:
				this.$ = new yy.BlockNode($$[$0 - 2], $$[$0 - 1], $$[$0])
				break;
			case 9:
				this.$ = $$[$0]
				break;
			case 10:
				this.$ = $$[$0]
				break;
			case 11:
				this.$ = new yy.ContentNode($$[$0])
				break;
			case 12:
				this.$ = new yy.CommentNode($$[$0])
				break;
			case 13:
				this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1])
				break;
			case 14:
				this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1])
				break;
			case 15:
				this.$ = $$[$0 - 1]
				break;
			case 16:
				this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1])
				break;
			case 17:
				this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1], true)
				break;
			case 18:
				this.$ = new yy.PartialNode($$[$0 - 1])
				break;
			case 19:
				this.$ = new yy.PartialNode($$[$0 - 2], $$[$0 - 1])
				break;
			case 20:
				break;
			case 21:
				this.$ = [ [ $$[$0 - 2] ].concat($$[$0 - 1]), $$[$0] ]
				break;
			case 22:
				this.$ = [ [ $$[$0 - 1] ].concat($$[$0]), null ]
				break;
			case 23:
				this.$ = [ [ $$[$0 - 1] ], $$[$0] ]
				break;
			case 24:
				this.$ = [ [ $$[$0] ], null ]
				break;
			case 25:
				$$[$0 - 1].push($$[$0]);
				this.$ = $$[$0 - 1];
				break;
			case 26:
				this.$ = [ $$[$0] ]
				break;
			case 27:
				this.$ = $$[$0]
				break;
			case 28:
				this.$ = new yy.StringNode($$[$0])
				break;
			case 29:
				this.$ = new yy.IntegerNode($$[$0])
				break;
			case 30:
				this.$ = new yy.BooleanNode($$[$0])
				break;
			case 31:
				this.$ = new yy.HashNode($$[$0])
				break;
			case 32:
				$$[$0 - 1].push($$[$0]);
				this.$ = $$[$0 - 1]
				break;
			case 33:
				this.$ = [ $$[$0] ]
				break;
			case 34:
				this.$ = [ $$[$0 - 2], $$[$0] ]
				break;
			case 35:
				this.$ = [ $$[$0 - 2], new yy.StringNode($$[$0]) ]
				break;
			case 36:
				this.$ = [ $$[$0 - 2], new yy.IntegerNode($$[$0]) ]
				break;
			case 37:
				this.$ = [ $$[$0 - 2], new yy.BooleanNode($$[$0]) ]
				break;
			case 38:
				this.$ = new yy.IdNode($$[$0])
				break;
			case 39:
				$$[$0 - 2].push($$[$0]);
				this.$ = $$[$0 - 2];
				break;
			case 40:
				this.$ = [ $$[$0] ]
				break;
			}
		},
		table : [ {
			3 : 1,
			4 : 2,
			5 : [ 2, 4 ],
			6 : 3,
			8 : 4,
			9 : 5,
			11 : 6,
			12 : 7,
			13 : 8,
			14 : [ 1, 9 ],
			15 : [ 1, 10 ],
			16 : [ 1, 12 ],
			19 : [ 1, 11 ],
			22 : [ 1, 13 ],
			23 : [ 1, 14 ],
			24 : [ 1, 15 ]
		}, {
			1 : [ 3 ]
		}, {
			5 : [ 1, 16 ]
		}, {
			5 : [ 2, 3 ],
			7 : 17,
			8 : 18,
			9 : 5,
			11 : 6,
			12 : 7,
			13 : 8,
			14 : [ 1, 9 ],
			15 : [ 1, 10 ],
			16 : [ 1, 12 ],
			19 : [ 1, 19 ],
			20 : [ 2, 3 ],
			22 : [ 1, 13 ],
			23 : [ 1, 14 ],
			24 : [ 1, 15 ]
		}, {
			5 : [ 2, 5 ],
			14 : [ 2, 5 ],
			15 : [ 2, 5 ],
			16 : [ 2, 5 ],
			19 : [ 2, 5 ],
			20 : [ 2, 5 ],
			22 : [ 2, 5 ],
			23 : [ 2, 5 ],
			24 : [ 2, 5 ]
		}, {
			4 : 20,
			6 : 3,
			8 : 4,
			9 : 5,
			11 : 6,
			12 : 7,
			13 : 8,
			14 : [ 1, 9 ],
			15 : [ 1, 10 ],
			16 : [ 1, 12 ],
			19 : [ 1, 11 ],
			20 : [ 2, 4 ],
			22 : [ 1, 13 ],
			23 : [ 1, 14 ],
			24 : [ 1, 15 ]
		}, {
			4 : 21,
			6 : 3,
			8 : 4,
			9 : 5,
			11 : 6,
			12 : 7,
			13 : 8,
			14 : [ 1, 9 ],
			15 : [ 1, 10 ],
			16 : [ 1, 12 ],
			19 : [ 1, 11 ],
			20 : [ 2, 4 ],
			22 : [ 1, 13 ],
			23 : [ 1, 14 ],
			24 : [ 1, 15 ]
		}, {
			5 : [ 2, 9 ],
			14 : [ 2, 9 ],
			15 : [ 2, 9 ],
			16 : [ 2, 9 ],
			19 : [ 2, 9 ],
			20 : [ 2, 9 ],
			22 : [ 2, 9 ],
			23 : [ 2, 9 ],
			24 : [ 2, 9 ]
		}, {
			5 : [ 2, 10 ],
			14 : [ 2, 10 ],
			15 : [ 2, 10 ],
			16 : [ 2, 10 ],
			19 : [ 2, 10 ],
			20 : [ 2, 10 ],
			22 : [ 2, 10 ],
			23 : [ 2, 10 ],
			24 : [ 2, 10 ]
		}, {
			5 : [ 2, 11 ],
			14 : [ 2, 11 ],
			15 : [ 2, 11 ],
			16 : [ 2, 11 ],
			19 : [ 2, 11 ],
			20 : [ 2, 11 ],
			22 : [ 2, 11 ],
			23 : [ 2, 11 ],
			24 : [ 2, 11 ]
		}, {
			5 : [ 2, 12 ],
			14 : [ 2, 12 ],
			15 : [ 2, 12 ],
			16 : [ 2, 12 ],
			19 : [ 2, 12 ],
			20 : [ 2, 12 ],
			22 : [ 2, 12 ],
			23 : [ 2, 12 ],
			24 : [ 2, 12 ]
		}, {
			17 : 22,
			21 : 23,
			33 : [ 1, 25 ],
			35 : 24
		}, {
			17 : 26,
			21 : 23,
			33 : [ 1, 25 ],
			35 : 24
		}, {
			17 : 27,
			21 : 23,
			33 : [ 1, 25 ],
			35 : 24
		}, {
			17 : 28,
			21 : 23,
			33 : [ 1, 25 ],
			35 : 24
		}, {
			21 : 29,
			33 : [ 1, 25 ],
			35 : 24
		}, {
			1 : [ 2, 1 ]
		}, {
			6 : 30,
			8 : 4,
			9 : 5,
			11 : 6,
			12 : 7,
			13 : 8,
			14 : [ 1, 9 ],
			15 : [ 1, 10 ],
			16 : [ 1, 12 ],
			19 : [ 1, 11 ],
			22 : [ 1, 13 ],
			23 : [ 1, 14 ],
			24 : [ 1, 15 ]
		}, {
			5 : [ 2, 6 ],
			14 : [ 2, 6 ],
			15 : [ 2, 6 ],
			16 : [ 2, 6 ],
			19 : [ 2, 6 ],
			20 : [ 2, 6 ],
			22 : [ 2, 6 ],
			23 : [ 2, 6 ],
			24 : [ 2, 6 ]
		}, {
			17 : 22,
			18 : [ 1, 31 ],
			21 : 23,
			33 : [ 1, 25 ],
			35 : 24
		}, {
			10 : 32,
			20 : [ 1, 33 ]
		}, {
			10 : 34,
			20 : [ 1, 33 ]
		}, {
			18 : [ 1, 35 ]
		}, {
			18 : [ 2, 24 ],
			21 : 40,
			25 : 36,
			26 : 37,
			27 : 38,
			28 : [ 1, 41 ],
			29 : [ 1, 42 ],
			30 : [ 1, 43 ],
			31 : 39,
			32 : 44,
			33 : [ 1, 45 ],
			35 : 24
		}, {
			18 : [ 2, 38 ],
			28 : [ 2, 38 ],
			29 : [ 2, 38 ],
			30 : [ 2, 38 ],
			33 : [ 2, 38 ],
			36 : [ 1, 46 ]
		}, {
			18 : [ 2, 40 ],
			28 : [ 2, 40 ],
			29 : [ 2, 40 ],
			30 : [ 2, 40 ],
			33 : [ 2, 40 ],
			36 : [ 2, 40 ]
		}, {
			18 : [ 1, 47 ]
		}, {
			18 : [ 1, 48 ]
		}, {
			18 : [ 1, 49 ]
		}, {
			18 : [ 1, 50 ],
			21 : 51,
			33 : [ 1, 25 ],
			35 : 24
		}, {
			5 : [ 2, 2 ],
			8 : 18,
			9 : 5,
			11 : 6,
			12 : 7,
			13 : 8,
			14 : [ 1, 9 ],
			15 : [ 1, 10 ],
			16 : [ 1, 12 ],
			19 : [ 1, 11 ],
			20 : [ 2, 2 ],
			22 : [ 1, 13 ],
			23 : [ 1, 14 ],
			24 : [ 1, 15 ]
		}, {
			14 : [ 2, 20 ],
			15 : [ 2, 20 ],
			16 : [ 2, 20 ],
			19 : [ 2, 20 ],
			22 : [ 2, 20 ],
			23 : [ 2, 20 ],
			24 : [ 2, 20 ]
		}, {
			5 : [ 2, 7 ],
			14 : [ 2, 7 ],
			15 : [ 2, 7 ],
			16 : [ 2, 7 ],
			19 : [ 2, 7 ],
			20 : [ 2, 7 ],
			22 : [ 2, 7 ],
			23 : [ 2, 7 ],
			24 : [ 2, 7 ]
		}, {
			21 : 52,
			33 : [ 1, 25 ],
			35 : 24
		}, {
			5 : [ 2, 8 ],
			14 : [ 2, 8 ],
			15 : [ 2, 8 ],
			16 : [ 2, 8 ],
			19 : [ 2, 8 ],
			20 : [ 2, 8 ],
			22 : [ 2, 8 ],
			23 : [ 2, 8 ],
			24 : [ 2, 8 ]
		}, {
			14 : [ 2, 14 ],
			15 : [ 2, 14 ],
			16 : [ 2, 14 ],
			19 : [ 2, 14 ],
			20 : [ 2, 14 ],
			22 : [ 2, 14 ],
			23 : [ 2, 14 ],
			24 : [ 2, 14 ]
		}, {
			18 : [ 2, 22 ],
			21 : 40,
			26 : 53,
			27 : 54,
			28 : [ 1, 41 ],
			29 : [ 1, 42 ],
			30 : [ 1, 43 ],
			31 : 39,
			32 : 44,
			33 : [ 1, 45 ],
			35 : 24
		}, {
			18 : [ 2, 23 ]
		}, {
			18 : [ 2, 26 ],
			28 : [ 2, 26 ],
			29 : [ 2, 26 ],
			30 : [ 2, 26 ],
			33 : [ 2, 26 ]
		}, {
			18 : [ 2, 31 ],
			32 : 55,
			33 : [ 1, 56 ]
		}, {
			18 : [ 2, 27 ],
			28 : [ 2, 27 ],
			29 : [ 2, 27 ],
			30 : [ 2, 27 ],
			33 : [ 2, 27 ]
		}, {
			18 : [ 2, 28 ],
			28 : [ 2, 28 ],
			29 : [ 2, 28 ],
			30 : [ 2, 28 ],
			33 : [ 2, 28 ]
		}, {
			18 : [ 2, 29 ],
			28 : [ 2, 29 ],
			29 : [ 2, 29 ],
			30 : [ 2, 29 ],
			33 : [ 2, 29 ]
		}, {
			18 : [ 2, 30 ],
			28 : [ 2, 30 ],
			29 : [ 2, 30 ],
			30 : [ 2, 30 ],
			33 : [ 2, 30 ]
		}, {
			18 : [ 2, 33 ],
			33 : [ 2, 33 ]
		}, {
			18 : [ 2, 40 ],
			28 : [ 2, 40 ],
			29 : [ 2, 40 ],
			30 : [ 2, 40 ],
			33 : [ 2, 40 ],
			34 : [ 1, 57 ],
			36 : [ 2, 40 ]
		}, {
			33 : [ 1, 58 ]
		}, {
			14 : [ 2, 13 ],
			15 : [ 2, 13 ],
			16 : [ 2, 13 ],
			19 : [ 2, 13 ],
			20 : [ 2, 13 ],
			22 : [ 2, 13 ],
			23 : [ 2, 13 ],
			24 : [ 2, 13 ]
		}, {
			5 : [ 2, 16 ],
			14 : [ 2, 16 ],
			15 : [ 2, 16 ],
			16 : [ 2, 16 ],
			19 : [ 2, 16 ],
			20 : [ 2, 16 ],
			22 : [ 2, 16 ],
			23 : [ 2, 16 ],
			24 : [ 2, 16 ]
		}, {
			5 : [ 2, 17 ],
			14 : [ 2, 17 ],
			15 : [ 2, 17 ],
			16 : [ 2, 17 ],
			19 : [ 2, 17 ],
			20 : [ 2, 17 ],
			22 : [ 2, 17 ],
			23 : [ 2, 17 ],
			24 : [ 2, 17 ]
		}, {
			5 : [ 2, 18 ],
			14 : [ 2, 18 ],
			15 : [ 2, 18 ],
			16 : [ 2, 18 ],
			19 : [ 2, 18 ],
			20 : [ 2, 18 ],
			22 : [ 2, 18 ],
			23 : [ 2, 18 ],
			24 : [ 2, 18 ]
		}, {
			18 : [ 1, 59 ]
		}, {
			18 : [ 1, 60 ]
		}, {
			18 : [ 2, 21 ]
		}, {
			18 : [ 2, 25 ],
			28 : [ 2, 25 ],
			29 : [ 2, 25 ],
			30 : [ 2, 25 ],
			33 : [ 2, 25 ]
		}, {
			18 : [ 2, 32 ],
			33 : [ 2, 32 ]
		}, {
			34 : [ 1, 57 ]
		}, {
			21 : 61,
			28 : [ 1, 62 ],
			29 : [ 1, 63 ],
			30 : [ 1, 64 ],
			33 : [ 1, 25 ],
			35 : 24
		}, {
			18 : [ 2, 39 ],
			28 : [ 2, 39 ],
			29 : [ 2, 39 ],
			30 : [ 2, 39 ],
			33 : [ 2, 39 ],
			36 : [ 2, 39 ]
		}, {
			5 : [ 2, 19 ],
			14 : [ 2, 19 ],
			15 : [ 2, 19 ],
			16 : [ 2, 19 ],
			19 : [ 2, 19 ],
			20 : [ 2, 19 ],
			22 : [ 2, 19 ],
			23 : [ 2, 19 ],
			24 : [ 2, 19 ]
		}, {
			5 : [ 2, 15 ],
			14 : [ 2, 15 ],
			15 : [ 2, 15 ],
			16 : [ 2, 15 ],
			19 : [ 2, 15 ],
			20 : [ 2, 15 ],
			22 : [ 2, 15 ],
			23 : [ 2, 15 ],
			24 : [ 2, 15 ]
		}, {
			18 : [ 2, 34 ],
			33 : [ 2, 34 ]
		}, {
			18 : [ 2, 35 ],
			33 : [ 2, 35 ]
		}, {
			18 : [ 2, 36 ],
			33 : [ 2, 36 ]
		}, {
			18 : [ 2, 37 ],
			33 : [ 2, 37 ]
		} ],
		defaultActions : {
			16 : [ 2, 1 ],
			37 : [ 2, 23 ],
			53 : [ 2, 21 ]
		},
		parseError : function parseError(str, hash) {
			throw new Error(str);
		},
		parse : function parse(input) {
			var self = this, stack = [ 0 ], vstack = [ null ], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
			this.lexer.setInput(input);
			this.lexer.yy = this.yy;
			this.yy.lexer = this.lexer;
			if (typeof this.lexer.yylloc == "undefined")
				this.lexer.yylloc = {};
			var yyloc = this.lexer.yylloc;
			lstack.push(yyloc);
			if (typeof this.yy.parseError === "function")
				this.parseError = this.yy.parseError;
			function popStack(n) {
				stack.length = stack.length - 2 * n;
				vstack.length = vstack.length - n;
				lstack.length = lstack.length - n;
			}
			function lex() {
				var token;
				token = self.lexer.lex() || 1;
				if (typeof token !== "number") {
					token = self.symbols_[token] || token;
				}
				return token;
			}
			var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
			while (true) {
				state = stack[stack.length - 1];
				if (this.defaultActions[state]) {
					action = this.defaultActions[state];
				} else {
					if (symbol == null)
						symbol = lex();
					action = table[state] && table[state][symbol];
				}
				if (typeof action === "undefined" || !action.length
						|| !action[0]) {
					if (!recovering) {
						expected = [];
						for (p in table[state])
							if (this.terminals_[p] && p > 2) {
								expected.push("'" + this.terminals_[p] + "'");
							}
						var errStr = "";
						if (this.lexer.showPosition) {
							errStr = "Parse error on line " + (yylineno + 1)
									+ ":\n" + this.lexer.showPosition()
									+ "\nExpecting " + expected.join(", ")
									+ ", got '" + this.terminals_[symbol] + "'";
						} else {
							errStr = "Parse error on line "
									+ (yylineno + 1)
									+ ": Unexpected "
									+ (symbol == 1 ? "end of input"
											: "'"
													+ (this.terminals_[symbol] || symbol)
													+ "'");
						}
						this.parseError(errStr, {
							text : this.lexer.match,
							token : this.terminals_[symbol] || symbol,
							line : this.lexer.yylineno,
							loc : yyloc,
							expected : expected
						});
					}
				}
				if (action[0] instanceof Array && action.length > 1) {
					throw new Error(
							"Parse Error: multiple actions possible at state: "
									+ state + ", token: " + symbol);
				}
				switch (action[0]) {
				case 1:
					stack.push(symbol);
					vstack.push(this.lexer.yytext);
					lstack.push(this.lexer.yylloc);
					stack.push(action[1]);
					symbol = null;
					if (!preErrorSymbol) {
						yyleng = this.lexer.yyleng;
						yytext = this.lexer.yytext;
						yylineno = this.lexer.yylineno;
						yyloc = this.lexer.yylloc;
						if (recovering > 0)
							recovering--;
					} else {
						symbol = preErrorSymbol;
						preErrorSymbol = null;
					}
					break;
				case 2:
					len = this.productions_[action[1]][1];
					yyval.$ = vstack[vstack.length - len];
					yyval._$ = {
						first_line : lstack[lstack.length - (len || 1)].first_line,
						last_line : lstack[lstack.length - 1].last_line,
						first_column : lstack[lstack.length - (len || 1)].first_column,
						last_column : lstack[lstack.length - 1].last_column
					};
					r = this.performAction.call(yyval, yytext, yyleng,
							yylineno, this.yy, action[1], vstack, lstack);
					if (typeof r !== "undefined") {
						return r;
					}
					if (len) {
						stack = stack.slice(0, -1 * len * 2);
						vstack = vstack.slice(0, -1 * len);
						lstack = lstack.slice(0, -1 * len);
					}
					stack.push(this.productions_[action[1]][0]);
					vstack.push(yyval.$);
					lstack.push(yyval._$);
					newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
					stack.push(newState);
					break;
				case 3:
					return true;
				}
			}
			return true;
		}
	};/* Jison generated lexer */
	var lexer = (function() {

		var lexer = ({
			EOF : 1,
			parseError : function parseError(str, hash) {
				if (this.yy.parseError) {
					this.yy.parseError(str, hash);
				} else {
					throw new Error(str);
				}
			},
			setInput : function(input) {
				this._input = input;
				this._more = this._less = this.done = false;
				this.yylineno = this.yyleng = 0;
				this.yytext = this.matched = this.match = '';
				this.conditionStack = [ 'INITIAL' ];
				this.yylloc = {
					first_line : 1,
					first_column : 0,
					last_line : 1,
					last_column : 0
				};
				return this;
			},
			input : function() {
				var ch = this._input[0];
				this.yytext += ch;
				this.yyleng++;
				this.match += ch;
				this.matched += ch;
				var lines = ch.match(/\n/);
				if (lines)
					this.yylineno++;
				this._input = this._input.slice(1);
				return ch;
			},
			unput : function(ch) {
				this._input = ch + this._input;
				return this;
			},
			more : function() {
				this._more = true;
				return this;
			},
			pastInput : function() {
				var past = this.matched.substr(0, this.matched.length
						- this.match.length);
				return (past.length > 20 ? '...' : '')
						+ past.substr(-20).replace(/\n/g, "");
			},
			upcomingInput : function() {
				var next = this.match;
				if (next.length < 20) {
					next += this._input.substr(0, 20 - next.length);
				}
				return (next.substr(0, 20) + (next.length > 20 ? '...' : ''))
						.replace(/\n/g, "");
			},
			showPosition : function() {
				var pre = this.pastInput();
				var c = new Array(pre.length + 1).join("-");
				return pre + this.upcomingInput() + "\n" + c + "^";
			},
			next : function() {
				if (this.done) {
					return this.EOF;
				}
				if (!this._input)
					this.done = true;

				var token, match, col, lines;
				if (!this._more) {
					this.yytext = '';
					this.match = '';
				}
				var rules = this._currentRules();
				for (var i = 0; i < rules.length; i++) {
					match = this._input.match(this.rules[rules[i]]);
					if (match) {
						lines = match[0].match(/\n.*/g);
						if (lines)
							this.yylineno += lines.length;
						this.yylloc = {
							first_line : this.yylloc.last_line,
							last_line : this.yylineno + 1,
							first_column : this.yylloc.last_column,
							last_column : lines ? lines[lines.length - 1].length - 1
									: this.yylloc.last_column + match[0].length
						}
						this.yytext += match[0];
						this.match += match[0];
						this.matches = match;
						this.yyleng = this.yytext.length;
						this._more = false;
						this._input = this._input.slice(match[0].length);
						this.matched += match[0];
						token = this.performAction
								.call(
										this,
										this.yy,
										this,
										rules[i],
										this.conditionStack[this.conditionStack.length - 1]);
						if (token)
							return token;
						else
							return;
					}
				}
				if (this._input === "") {
					return this.EOF;
				} else {
					this.parseError('Lexical error on line '
							+ (this.yylineno + 1) + '. Unrecognized text.\n'
							+ this.showPosition(), {
						text : "",
						token : null,
						line : this.yylineno
					});
				}
			},
			lex : function lex() {
				var r = this.next();
				if (typeof r !== 'undefined') {
					return r;
				} else {
					return this.lex();
				}
			},
			begin : function begin(condition) {
				this.conditionStack.push(condition);
			},
			popState : function popState() {
				return this.conditionStack.pop();
			},
			_currentRules : function _currentRules() {
				return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
			},
			topState : function() {
				return this.conditionStack[this.conditionStack.length - 2];
			},
			pushState : function begin(condition) {
				this.begin(condition);
			}
		});
		lexer.performAction = function anonymous(yy, yy_,
				$avoiding_name_collisions, YY_START) {

			var YYSTATE = YY_START
			switch ($avoiding_name_collisions) {
			case 0:
				if (yy_.yytext.slice(-1) !== "\\")
					this.begin("mu");
				if (yy_.yytext.slice(-1) === "\\")
					yy_.yytext = yy_.yytext.substr(0, yy_.yyleng - 1), this
							.begin("emu");
				if (yy_.yytext)
					return 14;

				break;
			case 1:
				return 14;
				break;
			case 2:
				this.popState();
				return 14;
				break;
			case 3:
				return 24;
				break;
			case 4:
				return 16;
				break;
			case 5:
				return 20;
				break;
			case 6:
				return 19;
				break;
			case 7:
				return 19;
				break;
			case 8:
				return 23;
				break;
			case 9:
				return 23;
				break;
			case 10:
				yy_.yytext = yy_.yytext.substr(3, yy_.yyleng - 5);
				this.popState();
				return 15;
				break;
			case 11:
				return 22;
				break;
			case 12:
				return 34;
				break;
			case 13:
				return 33;
				break;
			case 14:
				return 33;
				break;
			case 15:
				return 36;
				break;
			case 16: /* ignore whitespace */
				break;
			case 17:
				this.popState();
				return 18;
				break;
			case 18:
				this.popState();
				return 18;
				break;
			case 19:
				yy_.yytext = yy_.yytext.substr(1, yy_.yyleng - 2).replace(
						/\\"/g, '"');
				return 28;
				break;
			case 20:
				return 30;
				break;
			case 21:
				return 30;
				break;
			case 22:
				return 29;
				break;
			case 23:
				return 33;
				break;
			case 24:
				yy_.yytext = yy_.yytext.substr(1, yy_.yyleng - 2);
				return 33;
				break;
			case 25:
				return 'INVALID';
				break;
			case 26:
				return 5;
				break;
			}
		};
		lexer.rules = [ /^[^\x00]*?(?=(\{\{))/, /^[^\x00]+/,
				/^[^\x00]{2,}?(?=(\{\{))/, /^\{\{>/, /^\{\{#/, /^\{\{\//,
				/^\{\{\^/, /^\{\{\s*else\b/, /^\{\{\{/, /^\{\{&/,
				/^\{\{![\s\S]*?\}\}/, /^\{\{/, /^=/, /^\.(?=[} ])/, /^\.\./,
				/^[\/.]/, /^\s+/, /^\}\}\}/, /^\}\}/, /^"(\\["]|[^"])*"/,
				/^true(?=[}\s])/, /^false(?=[}\s])/, /^[0-9]+(?=[}\s])/,
				/^[a-zA-Z0-9_$-]+(?=[=}\s\/.])/, /^\[[^\]]*\]/, /^./, /^$/ ];
		lexer.conditions = {
			"mu" : {
				"rules" : [ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
						17, 18, 19, 20, 21, 22, 23, 24, 25, 26 ],
				"inclusive" : false
			},
			"emu" : {
				"rules" : [ 2 ],
				"inclusive" : false
			},
			"INITIAL" : {
				"rules" : [ 0, 1, 26 ],
				"inclusive" : true
			}
		};
		return lexer;
	})()
	parser.lexer = lexer;
	return parser;
})();
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
	exports.parser = handlebars;
	exports.parse = function() {
		return handlebars.parse.apply(handlebars, arguments);
	}
	exports.main = function commonjsMain(args) {
		if (!args[1])
			throw new Error('Usage: ' + args[0] + ' FILE');
		if (typeof process !== 'undefined') {
			var source = require('fs').readFileSync(
					require('path').join(process.cwd(), args[1]), "utf8");
		} else {
			var cwd = require("file").path(require("file").cwd());
			var source = cwd.join(args[1]).read({
				charset : "utf-8"
			});
		}
		return exports.parser.parse(source);
	}
	if (typeof module !== 'undefined' && require.main === module) {
		exports.main(typeof process !== 'undefined' ? process.argv.slice(1)
				: require("system").args);
	}
};
;
// lib/handlebars/compiler/base.js
Handlebars.Parser = handlebars;

Handlebars.parse = function(string) {
	Handlebars.Parser.yy = Handlebars.AST;
	return Handlebars.Parser.parse(string);
};

Handlebars.print = function(ast) {
	return new Handlebars.PrintVisitor().accept(ast);
};

Handlebars.logger = {
	DEBUG : 0,
	INFO : 1,
	WARN : 2,
	ERROR : 3,
	level : 3,

	// override in the host environment
	log : function(level, str) {
	}
};

Handlebars.log = function(level, str) {
	Handlebars.logger.log(level, str);
};
;
// lib/handlebars/compiler/ast.js
(function() {

	Handlebars.AST = {};

	Handlebars.AST.ProgramNode = function(statements, inverse) {
		this.type = "program";
		this.statements = statements;
		if (inverse) {
			this.inverse = new Handlebars.AST.ProgramNode(inverse);
		}
	};

	Handlebars.AST.MustacheNode = function(params, hash, unescaped) {
		this.type = "mustache";
		this.id = params[0];
		this.params = params.slice(1);
		this.hash = hash;
		this.escaped = !unescaped;
	};

	Handlebars.AST.PartialNode = function(id, context) {
		this.type = "partial";

		// TODO: disallow complex IDs

		this.id = id;
		this.context = context;
	};

	var verifyMatch = function(open, close) {
		if (open.original !== close.original) {
			throw new Handlebars.Exception(open.original + " doesn't match "
					+ close.original);
		}
	};

	Handlebars.AST.BlockNode = function(mustache, program, close) {
		verifyMatch(mustache.id, close);
		this.type = "block";
		this.mustache = mustache;
		this.program = program;
	};

	Handlebars.AST.InverseNode = function(mustache, program, close) {
		verifyMatch(mustache.id, close);
		this.type = "inverse";
		this.mustache = mustache;
		this.program = program;
	};

	Handlebars.AST.ContentNode = function(string) {
		this.type = "content";
		this.string = string;
	};

	Handlebars.AST.HashNode = function(pairs) {
		this.type = "hash";
		this.pairs = pairs;
	};

	Handlebars.AST.IdNode = function(parts) {
		this.type = "ID";
		this.original = parts.join(".");

		var dig = [], depth = 0;

		for (var i = 0, l = parts.length; i < l; i++) {
			var part = parts[i];

			if (part === "..") {
				depth++;
			} else if (part === "." || part === "this") {
				this.isScoped = true;
			} else {
				dig.push(part);
			}
		}

		this.parts = dig;
		this.string = dig.join('.');
		this.depth = depth;
		this.isSimple = (dig.length === 1) && (depth === 0);
	};

	Handlebars.AST.StringNode = function(string) {
		this.type = "STRING";
		this.string = string;
	};

	Handlebars.AST.IntegerNode = function(integer) {
		this.type = "INTEGER";
		this.integer = integer;
	};

	Handlebars.AST.BooleanNode = function(bool) {
		this.type = "BOOLEAN";
		this.bool = bool;
	};

	Handlebars.AST.CommentNode = function(comment) {
		this.type = "comment";
		this.comment = comment;
	};

})();
;
// lib/handlebars/utils.js
Handlebars.Exception = function(message) {
	var tmp = Error.prototype.constructor.apply(this, arguments);

	for ( var p in tmp) {
		if (tmp.hasOwnProperty(p)) {
			this[p] = tmp[p];
		}
	}

	this.message = tmp.message;
};
Handlebars.Exception.prototype = new Error;

// Build out our basic SafeString type
Handlebars.SafeString = function(string) {
	this.string = string;
};
Handlebars.SafeString.prototype.toString = function() {
	return this.string.toString();
};

(function() {
	var escape = {
		"<" : "&lt;",
		">" : "&gt;",
		'"' : "&quot;",
		"'" : "&#x27;",
		"`" : "&#x60;"
	};

	var badChars = /&(?!\w+;)|[<>"'`]/g;
	var possible = /[&<>"'`]/;

	var escapeChar = function(chr) {
		return escape[chr] || "&amp;";
	};

	Handlebars.Utils = {
		escapeExpression : function(string) {
			// don't escape SafeStrings, since they're already safe
			if (string instanceof Handlebars.SafeString) {
				return string.toString();
			} else if (string == null || string === false) {
				return "";
			}

			if (!possible.test(string)) {
				return string;
			}
			return string.replace(badChars, escapeChar);
		},

		isEmpty : function(value) {
			if (typeof value === "undefined") {
				return true;
			} else if (value === null) {
				return true;
			} else if (value === false) {
				return true;
			} else if (Object.prototype.toString.call(value) === "[object Array]"
					&& value.length === 0) {
				return true;
			} else {
				return false;
			}
		}
	};
})();
;
// lib/handlebars/compiler/compiler.js
Handlebars.Compiler = function() {
};
Handlebars.JavaScriptCompiler = function() {
};

(function(Compiler, JavaScriptCompiler) {
	Compiler.OPCODE_MAP = {
		appendContent : 1,
		getContext : 2,
		lookupWithHelpers : 3,
		lookup : 4,
		append : 5,
		invokeMustache : 6,
		appendEscaped : 7,
		pushString : 8,
		truthyOrFallback : 9,
		functionOrFallback : 10,
		invokeProgram : 11,
		invokePartial : 12,
		push : 13,
		assignToHash : 15,
		pushStringParam : 16
	};

	Compiler.MULTI_PARAM_OPCODES = {
		appendContent : 1,
		getContext : 1,
		lookupWithHelpers : 2,
		lookup : 1,
		invokeMustache : 3,
		pushString : 1,
		truthyOrFallback : 1,
		functionOrFallback : 1,
		invokeProgram : 3,
		invokePartial : 1,
		push : 1,
		assignToHash : 1,
		pushStringParam : 1
	};

	Compiler.DISASSEMBLE_MAP = {};

	for ( var prop in Compiler.OPCODE_MAP) {
		var value = Compiler.OPCODE_MAP[prop];
		Compiler.DISASSEMBLE_MAP[value] = prop;
	}

	Compiler.multiParamSize = function(code) {
		return Compiler.MULTI_PARAM_OPCODES[Compiler.DISASSEMBLE_MAP[code]];
	};

	Compiler.prototype = {
		compiler : Compiler,

		disassemble : function() {
			var opcodes = this.opcodes, opcode, nextCode;
			var out = [], str, name, value;

			for (var i = 0, l = opcodes.length; i < l; i++) {
				opcode = opcodes[i];

				if (opcode === 'DECLARE') {
					name = opcodes[++i];
					value = opcodes[++i];
					out.push("DECLARE " + name + " = " + value);
				} else {
					str = Compiler.DISASSEMBLE_MAP[opcode];

					var extraParams = Compiler.multiParamSize(opcode);
					var codes = [];

					for (var j = 0; j < extraParams; j++) {
						nextCode = opcodes[++i];

						if (typeof nextCode === "string") {
							nextCode = "\"" + nextCode.replace("\n", "\\n")
									+ "\"";
						}

						codes.push(nextCode);
					}

					str = str + " " + codes.join(" ");

					out.push(str);
				}
			}

			return out.join("\n");
		},

		guid : 0,

		compile : function(program, options) {
			this.children = [];
			this.depths = {
				list : []
			};
			this.options = options;

			// These changes will propagate to the other compiler components
			var knownHelpers = this.options.knownHelpers;
			this.options.knownHelpers = {
				'helperMissing' : true,
				'blockHelperMissing' : true,
				'each' : true,
				'if' : true,
				'unless' : true,
				'with' : true,
				'log' : true
			};
			if (knownHelpers) {
				for ( var name in knownHelpers) {
					this.options.knownHelpers[name] = knownHelpers[name];
				}
			}

			return this.program(program);
		},

		accept : function(node) {
			return this[node.type](node);
		},

		program : function(program) {
			var statements = program.statements, statement;
			this.opcodes = [];

			for (var i = 0, l = statements.length; i < l; i++) {
				statement = statements[i];
				this[statement.type](statement);
			}
			this.isSimple = l === 1;

			this.depths.list = this.depths.list.sort(function(a, b) {
				return a - b;
			});

			return this;
		},

		compileProgram : function(program) {
			var result = new this.compiler().compile(program, this.options);
			var guid = this.guid++;

			this.usePartial = this.usePartial || result.usePartial;

			this.children[guid] = result;

			for (var i = 0, l = result.depths.list.length; i < l; i++) {
				depth = result.depths.list[i];

				if (depth < 2) {
					continue;
				} else {
					this.addDepth(depth - 1);
				}
			}

			return guid;
		},

		block : function(block) {
			var mustache = block.mustache;
			var depth, child, inverse, inverseGuid;

			var params = this.setupStackForMustache(mustache);

			var programGuid = this.compileProgram(block.program);

			if (block.program.inverse) {
				inverseGuid = this.compileProgram(block.program.inverse);
				this.declare('inverse', inverseGuid);
			}

			this.opcode('invokeProgram', programGuid, params.length,
					!!mustache.hash);
			this.declare('inverse', null);
			this.opcode('append');
		},

		inverse : function(block) {
			var params = this.setupStackForMustache(block.mustache);

			var programGuid = this.compileProgram(block.program);

			this.declare('inverse', programGuid);

			this.opcode('invokeProgram', null, params.length,
					!!block.mustache.hash);
			this.declare('inverse', null);
			this.opcode('append');
		},

		hash : function(hash) {
			var pairs = hash.pairs, pair, val;

			this.opcode('push', '{}');

			for (var i = 0, l = pairs.length; i < l; i++) {
				pair = pairs[i];
				val = pair[1];

				this.accept(val);
				this.opcode('assignToHash', pair[0]);
			}
		},

		partial : function(partial) {
			var id = partial.id;
			this.usePartial = true;

			if (partial.context) {
				this.ID(partial.context);
			} else {
				this.opcode('push', 'depth0');
			}

			this.opcode('invokePartial', id.original);
			this.opcode('append');
		},

		content : function(content) {
			this.opcode('appendContent', content.string);
		},

		mustache : function(mustache) {
			var params = this.setupStackForMustache(mustache);

			this.opcode('invokeMustache', params.length, mustache.id.original,
					!!mustache.hash);

			if (mustache.escaped && !this.options.noEscape) {
				this.opcode('appendEscaped');
			} else {
				this.opcode('append');
			}
		},

		ID : function(id) {
			this.addDepth(id.depth);

			this.opcode('getContext', id.depth);

			this.opcode('lookupWithHelpers', id.parts[0] || null,
					id.isScoped || false);

			for (var i = 1, l = id.parts.length; i < l; i++) {
				this.opcode('lookup', id.parts[i]);
			}
		},

		STRING : function(string) {
			this.opcode('pushString', string.string);
		},

		INTEGER : function(integer) {
			this.opcode('push', integer.integer);
		},

		BOOLEAN : function(bool) {
			this.opcode('push', bool.bool);
		},

		comment : function() {
		},

		// HELPERS
		pushParams : function(params) {
			var i = params.length, param;

			while (i--) {
				param = params[i];

				if (this.options.stringParams) {
					if (param.depth) {
						this.addDepth(param.depth);
					}

					this.opcode('getContext', param.depth || 0);
					this.opcode('pushStringParam', param.string);
				} else {
					this[param.type](param);
				}
			}
		},

		opcode : function(name, val1, val2, val3) {
			this.opcodes.push(Compiler.OPCODE_MAP[name]);
			if (val1 !== undefined) {
				this.opcodes.push(val1);
			}
			if (val2 !== undefined) {
				this.opcodes.push(val2);
			}
			if (val3 !== undefined) {
				this.opcodes.push(val3);
			}
		},

		declare : function(name, value) {
			this.opcodes.push('DECLARE');
			this.opcodes.push(name);
			this.opcodes.push(value);
		},

		addDepth : function(depth) {
			if (depth === 0) {
				return;
			}

			if (!this.depths[depth]) {
				this.depths[depth] = true;
				this.depths.list.push(depth);
			}
		},

		setupStackForMustache : function(mustache) {
			var params = mustache.params;

			this.pushParams(params);

			if (mustache.hash) {
				this.hash(mustache.hash);
			}

			this.ID(mustache.id);

			return params;
		}
	};

	JavaScriptCompiler.prototype = {
		// PUBLIC API: You can override these methods in a subclass to provide
		// alternative compiled forms for name lookup and buffering semantics
		nameLookup : function(parent, name, type) {
			if (/^[0-9]+$/.test(name)) {
				return parent + "[" + name + "]";
			} else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
				return parent + "." + name;
			} else {
				return parent + "['" + name + "']";
			}
		},

		appendToBuffer : function(string) {
			if (this.environment.isSimple) {
				return "return " + string + ";";
			} else {
				return "buffer += " + string + ";";
			}
		},

		initializeBuffer : function() {
			return this.quotedString("");
		},

		namespace : "Handlebars",
		// END PUBLIC API

		compile : function(environment, options, context, asObject) {
			this.environment = environment;
			this.options = options || {};

			this.name = this.environment.name;
			this.isChild = !!context;
			this.context = context || {
				programs : [],
				aliases : {
					self : 'this'
				},
				registers : {
					list : []
				}
			};

			this.preamble();

			this.stackSlot = 0;
			this.stackVars = [];

			this.compileChildren(environment, options);

			var opcodes = environment.opcodes, opcode;

			this.i = 0;

			for (l = opcodes.length; this.i < l; this.i++) {
				opcode = this.nextOpcode(0);

				if (opcode[0] === 'DECLARE') {
					this.i = this.i + 2;
					this[opcode[1]] = opcode[2];
				} else {
					this.i = this.i + opcode[1].length;
					this[opcode[0]].apply(this, opcode[1]);
				}
			}

			return this.createFunctionContext(asObject);
		},

		nextOpcode : function(n) {
			var opcodes = this.environment.opcodes, opcode = opcodes[this.i + n], name, val;
			var extraParams, codes;

			if (opcode === 'DECLARE') {
				name = opcodes[this.i + 1];
				val = opcodes[this.i + 2];
				return [ 'DECLARE', name, val ];
			} else {
				name = Compiler.DISASSEMBLE_MAP[opcode];

				extraParams = Compiler.multiParamSize(opcode);
				codes = [];

				for (var j = 0; j < extraParams; j++) {
					codes.push(opcodes[this.i + j + 1 + n]);
				}

				return [ name, codes ];
			}
		},

		eat : function(opcode) {
			this.i = this.i + opcode.length;
		},

		preamble : function() {
			var out = [];

			// this register will disambiguate helper lookup from finding a
			// function in
			// a context. This is necessary for mustache compatibility, which
			// requires
			// that context functions in blocks are evaluated by
			// blockHelperMissing, and
			// then proceed as if the resulting value was provided to
			// blockHelperMissing.
			this.useRegister('foundHelper');

			if (!this.isChild) {
				var namespace = this.namespace;
				var copies = "helpers = helpers || " + namespace + ".helpers;";
				if (this.environment.usePartial) {
					copies = copies + " partials = partials || " + namespace
							+ ".partials;";
				}
				out.push(copies);
			} else {
				out.push('');
			}

			if (!this.environment.isSimple) {
				out.push(", buffer = " + this.initializeBuffer());
			} else {
				out.push("");
			}

			// track the last context pushed into place to allow skipping the
			// getContext opcode when it would be a noop
			this.lastContext = 0;
			this.source = out;
		},

		createFunctionContext : function(asObject) {
			var locals = this.stackVars;
			if (!this.isChild) {
				locals = locals.concat(this.context.registers.list);
			}

			if (locals.length > 0) {
				this.source[1] = this.source[1] + ", " + locals.join(", ");
			}

			// Generate minimizer alias mappings
			if (!this.isChild) {
				var aliases = []
				for ( var alias in this.context.aliases) {
					this.source[1] = this.source[1] + ', ' + alias + '='
							+ this.context.aliases[alias];
				}
			}

			if (this.source[1]) {
				this.source[1] = "var " + this.source[1].substring(2) + ";";
			}

			// Merge children
			if (!this.isChild) {
				this.source[1] += '\n' + this.context.programs.join('\n')
						+ '\n';
			}

			if (!this.environment.isSimple) {
				this.source.push("return buffer;");
			}

			var params = this.isChild ? [ "depth0", "data" ] : [ "Handlebars",
					"depth0", "helpers", "partials", "data" ];

			for (var i = 0, l = this.environment.depths.list.length; i < l; i++) {
				params.push("depth" + this.environment.depths.list[i]);
			}

			if (asObject) {
				params.push(this.source.join("\n  "));

				return Function.apply(this, params);
			} else {
				var functionSource = 'function ' + (this.name || '') + '('
						+ params.join(',') + ') {\n  '
						+ this.source.join("\n  ") + '}';
				Handlebars
						.log(Handlebars.logger.DEBUG, functionSource + "\n\n");
				return functionSource;
			}
		},

		appendContent : function(content) {
			this.source.push(this.appendToBuffer(this.quotedString(content)));
		},

		append : function() {
			var local = this.popStack();
			this.source.push("if(" + local + " || " + local + " === 0) { "
					+ this.appendToBuffer(local) + " }");
			if (this.environment.isSimple) {
				this.source.push("else { " + this.appendToBuffer("''") + " }");
			}
		},

		appendEscaped : function() {
			var opcode = this.nextOpcode(1), extra = "";
			this.context.aliases.escapeExpression = 'this.escapeExpression';

			if (opcode[0] === 'appendContent') {
				extra = " + " + this.quotedString(opcode[1][0]);
				this.eat(opcode);
			}

			this.source.push(this.appendToBuffer("escapeExpression("
					+ this.popStack() + ")" + extra));
		},

		getContext : function(depth) {
			if (this.lastContext !== depth) {
				this.lastContext = depth;
			}
		},

		lookupWithHelpers : function(name, isScoped) {
			if (name) {
				var topStack = this.nextStack();

				this.usingKnownHelper = false;

				var toPush;
				if (!isScoped && this.options.knownHelpers[name]) {
					toPush = topStack + " = "
							+ this.nameLookup('helpers', name, 'helper');
					this.usingKnownHelper = true;
				} else if (isScoped || this.options.knownHelpersOnly) {
					toPush = topStack
							+ " = "
							+ this.nameLookup('depth' + this.lastContext, name,
									'context');
				} else {
					this.register('foundHelper', this.nameLookup('helpers',
							name, 'helper'));
					toPush = topStack
							+ " = foundHelper || "
							+ this.nameLookup('depth' + this.lastContext, name,
									'context');
				}

				toPush += ';';
				this.source.push(toPush);
			} else {
				this.pushStack('depth' + this.lastContext);
			}
		},

		lookup : function(name) {
			var topStack = this.topStack();
			this.source.push(topStack + " = (" + topStack + " === null || "
					+ topStack + " === undefined || " + topStack
					+ " === false ? " + topStack + " : "
					+ this.nameLookup(topStack, name, 'context') + ");");
		},

		pushStringParam : function(string) {
			this.pushStack('depth' + this.lastContext);
			this.pushString(string);
		},

		pushString : function(string) {
			this.pushStack(this.quotedString(string));
		},

		push : function(name) {
			this.pushStack(name);
		},

		invokeMustache : function(paramSize, original, hasHash) {
			this
					.populateParams(
							paramSize,
							this.quotedString(original),
							"{}",
							null,
							hasHash,
							function(nextStack, helperMissingString, id) {
								if (!this.usingKnownHelper) {
									this.context.aliases.helperMissing = 'helpers.helperMissing';
									this.context.aliases.undef = 'void 0';
									this.source.push("else if(" + id
											+ "=== undef) { " + nextStack
											+ " = helperMissing.call("
											+ helperMissingString + "); }");
									if (nextStack !== id) {
										this.source.push("else { " + nextStack
												+ " = " + id + "; }");
									}
								}
							});
		},

		invokeProgram : function(guid, paramSize, hasHash) {
			var inverse = this.programExpression(this.inverse);
			var mainProgram = this.programExpression(guid);

			this
					.populateParams(
							paramSize,
							null,
							mainProgram,
							inverse,
							hasHash,
							function(nextStack, helperMissingString, id) {
								if (!this.usingKnownHelper) {
									this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
									this.source.push("else { " + nextStack
											+ " = blockHelperMissing.call("
											+ helperMissingString + "); }");
								}
							});
		},

		populateParams : function(paramSize, helperId, program, inverse,
				hasHash, fn) {
			var needsRegister = hasHash || this.options.stringParams || inverse
					|| this.options.data;
			var id = this.popStack(), nextStack;
			var params = [], param, stringParam, stringOptions;

			if (needsRegister) {
				this.register('tmp1', program);
				stringOptions = 'tmp1';
			} else {
				stringOptions = '{ hash: {} }';
			}

			if (needsRegister) {
				var hash = (hasHash ? this.popStack() : '{}');
				this.source.push('tmp1.hash = ' + hash + ';');
			}

			if (this.options.stringParams) {
				this.source.push('tmp1.contexts = [];');
			}

			for (var i = 0; i < paramSize; i++) {
				param = this.popStack();
				params.push(param);

				if (this.options.stringParams) {
					this.source.push('tmp1.contexts.push(' + this.popStack()
							+ ');');
				}
			}

			if (inverse) {
				this.source.push('tmp1.fn = tmp1;');
				this.source.push('tmp1.inverse = ' + inverse + ';');
			}

			if (this.options.data) {
				this.source.push('tmp1.data = data;');
			}

			params.push(stringOptions);

			this.populateCall(params, id, helperId || id, fn, program !== '{}');
		},

		populateCall : function(params, id, helperId, fn, program) {
			var paramString = [ "depth0" ].concat(params).join(", ");
			var helperMissingString = [ "depth0" ].concat(helperId).concat(
					params).join(", ");

			var nextStack = this.nextStack();

			if (this.usingKnownHelper) {
				this.source.push(nextStack + " = " + id + ".call("
						+ paramString + ");");
			} else {
				this.context.aliases.functionType = '"function"';
				var condition = program ? "foundHelper && " : ""
				this.source.push("if(" + condition + "typeof " + id
						+ " === functionType) { " + nextStack + " = " + id
						+ ".call(" + paramString + "); }");
			}
			fn.call(this, nextStack, helperMissingString, id);
			this.usingKnownHelper = false;
		},

		invokePartial : function(context) {
			params = [ this.nameLookup('partials', context, 'partial'),
					"'" + context + "'", this.popStack(), "helpers", "partials" ];

			if (this.options.data) {
				params.push("data");
			}

			this.pushStack("self.invokePartial(" + params.join(", ") + ");");
		},

		assignToHash : function(key) {
			var value = this.popStack();
			var hash = this.topStack();

			this.source.push(hash + "['" + key + "'] = " + value + ";");
		},

		// HELPERS

		compiler : JavaScriptCompiler,

		compileChildren : function(environment, options) {
			var children = environment.children, child, compiler;

			for (var i = 0, l = children.length; i < l; i++) {
				child = children[i];
				compiler = new this.compiler();

				this.context.programs.push(''); // Placeholder to prevent name
												// conflicts for nested children
				var index = this.context.programs.length;
				child.index = index;
				child.name = 'program' + index;
				this.context.programs[index] = compiler.compile(child, options,
						this.context);
			}
		},

		programExpression : function(guid) {
			if (guid == null) {
				return "self.noop";
			}

			var child = this.environment.children[guid], depths = child.depths.list;
			var programParams = [ child.index, child.name, "data" ];

			for (var i = 0, l = depths.length; i < l; i++) {
				depth = depths[i];

				if (depth === 1) {
					programParams.push("depth0");
				} else {
					programParams.push("depth" + (depth - 1));
				}
			}

			if (depths.length === 0) {
				return "self.program(" + programParams.join(", ") + ")";
			} else {
				programParams.shift();
				return "self.programWithDepth(" + programParams.join(", ")
						+ ")";
			}
		},

		register : function(name, val) {
			this.useRegister(name);
			this.source.push(name + " = " + val + ";");
		},

		useRegister : function(name) {
			if (!this.context.registers[name]) {
				this.context.registers[name] = true;
				this.context.registers.list.push(name);
			}
		},

		pushStack : function(item) {
			this.source.push(this.nextStack() + " = " + item + ";");
			return "stack" + this.stackSlot;
		},

		nextStack : function() {
			this.stackSlot++;
			if (this.stackSlot > this.stackVars.length) {
				this.stackVars.push("stack" + this.stackSlot);
			}
			return "stack" + this.stackSlot;
		},

		popStack : function() {
			return "stack" + this.stackSlot--;
		},

		topStack : function() {
			return "stack" + this.stackSlot;
		},

		quotedString : function(str) {
			return '"'
					+ str.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(
							/\n/g, '\\n').replace(/\r/g, '\\r') + '"';
		}
	};

	var reservedWords = ("break else new var" + " case finally return void"
			+ " catch for switch while" + " continue function this with"
			+ " default if throw" + " delete in try" + " do instanceof typeof"
			+ " abstract enum int short" + " boolean export interface static"
			+ " byte extends long super" + " char final native synchronized"
			+ " class float package throws" + " const goto private transient"
			+ " debugger implements protected volatile"
			+ " double import public let yield").split(" ");

	var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};

	for (var i = 0, l = reservedWords.length; i < l; i++) {
		compilerWords[reservedWords[i]] = true;
	}

	JavaScriptCompiler.isValidJavaScriptVariableName = function(name) {
		if (!JavaScriptCompiler.RESERVED_WORDS[name]
				&& /^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(name)) {
			return true;
		}
		return false;
	}

})(Handlebars.Compiler, Handlebars.JavaScriptCompiler);

Handlebars.precompile = function(string, options) {
	options = options || {};

	var ast = Handlebars.parse(string);
	var environment = new Handlebars.Compiler().compile(ast, options);
	return new Handlebars.JavaScriptCompiler().compile(environment, options);
};

Handlebars.compile = function(string, options) {
	options = options || {};

	var compiled;
	function compile() {
		var ast = Handlebars.parse(string);
		var environment = new Handlebars.Compiler().compile(ast, options);
		var templateSpec = new Handlebars.JavaScriptCompiler().compile(
				environment, options, undefined, true);
		return Handlebars.template(templateSpec);
	}

	// Template is only compiled on first use and cached after that point.
	return function(context, options) {
		if (!compiled) {
			compiled = compile();
		}
		return compiled.call(this, context, options);
	};
};
;
// lib/handlebars/runtime.js
Handlebars.VM = {
	template : function(templateSpec) {
		// Just add water
		var container = {
			escapeExpression : Handlebars.Utils.escapeExpression,
			invokePartial : Handlebars.VM.invokePartial,
			programs : [],
			program : function(i, fn, data) {
				var programWrapper = this.programs[i];
				if (data) {
					return Handlebars.VM.program(fn, data);
				} else if (programWrapper) {
					return programWrapper;
				} else {
					programWrapper = this.programs[i] = Handlebars.VM
							.program(fn);
					return programWrapper;
				}
			},
			programWithDepth : Handlebars.VM.programWithDepth,
			noop : Handlebars.VM.noop
		};

		return function(context, options) {
			options = options || {};
			return templateSpec.call(container, Handlebars, context,
					options.helpers, options.partials, options.data);
		};
	},

	programWithDepth : function(fn, data, $depth) {
		var args = Array.prototype.slice.call(arguments, 2);

		return function(context, options) {
			options = options || {};

			return fn.apply(this, [ context, options.data || data ]
					.concat(args));
		};
	},
	program : function(fn, data) {
		return function(context, options) {
			options = options || {};

			return fn(context, options.data || data);
		};
	},
	noop : function() {
		return "";
	},
	invokePartial : function(partial, name, context, helpers, partials, data) {
		options = {
			helpers : helpers,
			partials : partials,
			data : data
		};

		if (partial === undefined) {
			throw new Handlebars.Exception("The partial " + name
					+ " could not be found");
		} else if (partial instanceof Function) {
			return partial(context, options);
		} else if (!Handlebars.compile) {
			throw new Handlebars.Exception(
					"The partial "
							+ name
							+ " could not be compiled when running in runtime-only mode");
		} else {
			partials[name] = Handlebars.compile(partial);
			return partials[name](context, options);
		}
	}
};

Handlebars.template = Handlebars.VM.template;
;
